package com.borrowed.book.weixin.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.borrowed.book.book.constant.BookConstant;
import com.borrowed.book.book.domain.CardOrderDetailDto;
import com.borrowed.book.book.domain.SelectPayOrderOutDto;
import com.borrowed.book.book.mapper.SPayOrderDetailMapper;
import com.borrowed.book.book.mapper.SPayOrderMapper;
import com.borrowed.book.book.service.WxOrderService;
import com.borrowed.book.coupon.service.SCouponUserService;
import com.borrowed.book.membercard.service.SMemberCardService;
import com.borrowed.book.system.util.SignUtil;
import com.borrowed.book.system.util.StringUtils;
import com.borrowed.book.user.domain.SUser;
import com.borrowed.book.user.mapper.SUserMapper;
import com.borrowed.book.weixin.WxUtil.WxUtil;
import com.borrowed.book.weixin.constant.WxConstant;
import com.borrowed.book.weixin.entity.SOrderPay;
import com.borrowed.book.weixin.entity.SOrderPayScore;
import com.borrowed.book.weixin.entity.SOrderRefund;
import com.borrowed.book.weixin.service.SOrderPayScoreService;
import com.borrowed.book.weixin.service.SOrderPayService;
import com.borrowed.book.weixin.service.SOrderRefundService;
import com.borrowed.book.weixin.service.WxPayService;
import com.borrowed.book.weixin.wxVo.*;
import com.wechat.pay.contrib.apache.httpclient.WechatPayHttpClientBuilder;
import com.wechat.pay.contrib.apache.httpclient.auth.AutoUpdateCertificatesVerifier;
import com.wechat.pay.contrib.apache.httpclient.auth.PrivateKeySigner;
import com.wechat.pay.contrib.apache.httpclient.auth.WechatPay2Credentials;
import com.wechat.pay.contrib.apache.httpclient.auth.WechatPay2Validator;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.util.EntityUtils;
import org.apache.log4j.Logger;
import org.apache.shiro.SecurityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.IOException;
import java.math.BigDecimal;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.SignatureException;
import java.security.spec.InvalidKeySpecException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class WxPayServiceImpl implements WxPayService {
    private static org.apache.log4j.Logger log = Logger.getLogger(WxPayServiceImpl.class.getClass());

    @Value("${weixin.appId}")
    private String appId;
    @Value("${weixin.mchId}")
    private String mchId;
    @Value("${weixin.apiV3Key}")
    private String apiV3Key;
    @Value("${weixin.mchSerialNo}")
    private String mchSerialNo;
    @Value("${weixin.serviceId}")
    private String serviceId;
    @Value("${weixin.notifyUrl}")
    private String notifyUrl;
    @Value("${weixin.scoreNotifyUrl}")
    private String scoreNotifyUrl;
    @Value("${weixin.refundNotifyUrl}")
    private String refundNotifyUrl;

    @Autowired
    private SPayOrderDetailMapper payOrderDetailMapper;

    @Autowired
    private SPayOrderMapper orderMapper;
    @Autowired
    private SCouponUserService couponUserService;
    @Autowired
    private SUserMapper userMapper;
    @Autowired
    private SMemberCardService memCardService;
    @Autowired
    private WxOrderService wxOrderService;
    @Autowired
    private SOrderRefundService orderRefundService;
    @Autowired
    private SOrderPayService orderPayService;
    @Autowired
    private SOrderPayScoreService orderPayScoreService;


    /**
     * JSAPI预支付
     * @param total 支付价格
     * @param orderNo 订单
     * 官方接口说明：https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_5_1.shtml
     * @return
     * @throws Exception
     */
    @Override
    public JSONObject PayTransaction(BigDecimal total, String orderNo) throws Exception {
        SUser sysUser = (SUser) SecurityUtils.getSubject().getPrincipal();
        String openid=sysUser.getOpenid();

        File directory = new File("..");// 参数为空
        String courseFile = directory.getCanonicalPath()+"/apiclient_key.pem";
        PrivateKey privateKey= WxUtil.getPrivateKey(courseFile);

        JSONObject map = new JSONObject();

        // 加载平台证书（mchId：商户号,mchSerialNo：商户证书序列号,apiV3Key：V3秘钥）
        AutoUpdateCertificatesVerifier verifier = new AutoUpdateCertificatesVerifier(new WechatPay2Credentials(mchId, new PrivateKeySigner(mchSerialNo, privateKey)),apiV3Key.getBytes("utf-8"));

        // 初始化httpClient
        HttpClient httpClient = WechatPayHttpClientBuilder.create().withMerchant(mchId, mchSerialNo, privateKey).withValidator(new WechatPay2Validator(verifier)).build();

        //请求URL
        HttpPost httpPost = new HttpPost(WxConstant.payCreate);
        //随机字符串  根据自己工具类写
        String nonceStr = RandomStringUtils.randomAlphanumeric(5);
        //时间戳 根据自己工具类写
        String timeStamp = String.valueOf(System.currentTimeMillis());

        //微信金额是按照分来的，所以要乘以100
        total=total.multiply(new BigDecimal(100));

        PayTransactionVo payTransactionVo=new PayTransactionVo();
        PayAmount payAmount=new PayAmount();
        payAmount.setTotal(total.intValue());
        payAmount.setCurrency("CNY");
        payTransactionVo.setAmount(payAmount);
        payTransactionVo.setAppid(appId);
        payTransactionVo.setMchid(mchId);
        payTransactionVo.setDescription("信言绘本图书租赁");
        payTransactionVo.setNotify_url(notifyUrl);
        payTransactionVo.setOut_trade_no(orderNo);
        Payer payer=new Payer();
        payer.setOpenid(openid);
        payTransactionVo.setPayer(payer);

        StringEntity entity = new StringEntity(JSONObject.toJSONString(payTransactionVo),"utf-8");

        entity.setContentType("application/json");
        httpPost.setEntity(entity);
        httpPost.setHeader("Accept", "application/json");

        //完成签名并执行请求
        String result = "";
        CloseableHttpResponse response = (CloseableHttpResponse) httpClient.execute(httpPost);
        try {
            int statusCode = response.getStatusLine().getStatusCode();
            if (statusCode == 200) {
                log.info("预付款创建成功，success,return body = " + EntityUtils.toString(response.getEntity()));
                JSONObject jsonObject = JSONObject.parseObject(EntityUtils.toString(response.getEntity()));
                result = "prepay_id=" + jsonObject.getString("prepay_id");;
            } else {
                result = "failed,resp code = " + statusCode+ ",return body = " + EntityUtils.toString(response.getEntity());
                log.error(result);
                throw new IOException(result);
            }
        } finally {
            response.close();
        }

        String pendingPaySign = appId + "\n" + timeStamp + "\n" + nonceStr + "\n" + result + "\n";
        String paySign = SignUtil.encodeBase64(SignUtil.sign256(pendingPaySign, privateKey));
        map.put("appId", appId);
        map.put("timeStamp", timeStamp);
        map.put("nonceStr", nonceStr);
        map.put("package", result);
        map.put("signType", "RSA");
        map.put("paySign", paySign);
        return map;
    }

    /**
     * 官方接口说明：https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_5_5.shtml
     * @param request
     * @param response
     * @return
     * @throws Exception
     */
    @Override
    public String PayNotifyResult(HttpServletRequest request, HttpServletResponse response) throws Exception {
        JSONObject map = new JSONObject();
        String result = WxUtil.readData(request);
        // 需要通过证书序列号查找对应的证书，verifyNotify 中有验证证书的序列号
        String plainText = WxUtil.verifyNotify(result, apiV3Key);
        if (StringUtils.isNotEmpty(plainText)) {
            response.setStatus(200);
            map.put("code", "SUCCESS");
            map.put("message", "SUCCESS");
            JSONObject jsonObject=JSONObject.parseObject(plainText);

            //保存支付记录信息
            SOrderPay sOrderPay=JSON.toJavaObject(jsonObject,SOrderPay.class);
            String openid=jsonObject.getJSONObject("payer").getString("openid");
            sOrderPay.setOpenid(openid);
            Integer total=jsonObject.getJSONObject("amount").getInteger("total");
            Integer payerTotal=jsonObject.getJSONObject("amount").getInteger("payer_total");
            String currency=jsonObject.getJSONObject("amount").getString("currency");
            String payerCurrency=jsonObject.getJSONObject("amount").getString("currency");
            sOrderPay.setTotal(total);
            sOrderPay.setCurrency(currency);
            sOrderPay.setPayerCurrency(payerCurrency);
            sOrderPay.setPayerTotal(payerTotal);
            orderPayService.save(sOrderPay);

            //支付成功后，订单信息更新
            wxOrderService.paySucessUpdateOrder(sOrderPay.getOutTradeNo(),sOrderPay.getTradeState(), sOrderPay.getOpenid(),sOrderPay.getTransactionId());
        } else {
            response.setStatus(500);
            map.put("code", "ERROR");
            map.put("message", "签名错误");
        }
        //通知应答
        //支付通知http应答码为200或204才会当作正常接收，当回调处理异常时，应答的HTTP状态码应为500，或者4xx
        response.setCharacterEncoding("utf-8");
        response.setContentType("application/json; charset=utf-8");
        BufferedOutputStream out = new BufferedOutputStream(response.getOutputStream());
        out.write(plainText.getBytes());
        out.flush();
        out.close();

        return null;
    }

    /**
     * 官方接口说明：https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_5_9.shtml
     * @param refund
     * @param orderNo
     * @param reason
     * @return
     * @throws Exception
     */
    @Override
    public JSONObject PayRefund(BigDecimal refund, String orderNo, String reason) throws Exception {
        JSONObject jsonObject = new JSONObject();
        HttpClient httpClient=WxUtil.getHttpClient(mchId,mchSerialNo,apiV3Key);
        //请求URL
        HttpPost httpPost = new HttpPost(WxConstant.reFund);
        // 请求body参数
        PayRefundVo payRefundVo=new PayRefundVo();
        payRefundVo.setOut_trade_no(orderNo);
        PayRefundAmount payRefundAmount=new PayRefundAmount();
        //退款金额以分为单位
        SelectPayOrderOutDto orderInfo=orderMapper.selectPayOrderById(orderNo);
        BigDecimal total=orderInfo.getPayAmount().multiply(new BigDecimal(100));
        refund=refund.multiply(new BigDecimal(100));
        payRefundAmount.setRefund(refund.intValue());
        payRefundAmount.setCurrency("CNY");
        payRefundAmount.setTotal(total.intValue());
        payRefundVo.setAmount(payRefundAmount);
        String outRefundNo=WxUtil.CreateOutRefundNo();
        payRefundVo.setOut_refund_no(outRefundNo);
        payRefundVo.setReason(reason);
        payRefundVo.setNotify_url(refundNotifyUrl);

        StringEntity entity = new StringEntity(JSONObject.toJSONString(payRefundVo),"utf-8");
        entity.setContentType("application/json");
        httpPost.setEntity(entity);
        httpPost.setHeader("Accept", "application/json");
        //完成签名并执行请求
        String result = "";
        CloseableHttpResponse response = (CloseableHttpResponse) httpClient.execute(httpPost);
        try {
            int statusCode = response.getStatusLine().getStatusCode();
            if (statusCode == 200) {
                log.info("申请退款成功：success,return body = " + EntityUtils.toString(response.getEntity()));
                jsonObject = JSONObject.parseObject(EntityUtils.toString(response.getEntity()));
                SOrderRefund sOrderRefund= JSON.toJavaObject(jsonObject,SOrderRefund.class);
                sOrderRefund.setOrderNo(jsonObject.getString("out_refund_no"));
                sOrderRefund.setTotal(jsonObject.getJSONObject("amount").getInteger("total"));
                sOrderRefund.setRefund(jsonObject.getJSONObject("amount").getInteger("refund"));
                sOrderRefund.setPayerTotal(jsonObject.getJSONObject("amount").getInteger("payer_total"));
                sOrderRefund.setPayerRefund(jsonObject.getJSONObject("amount").getInteger("payer_refund"));
                sOrderRefund.setSettlementRefund(jsonObject.getJSONObject("amount").getInteger("settlement_refund"));
                sOrderRefund.setSettlementTotal(jsonObject.getJSONObject("amount").getInteger("settlement_total"));
                sOrderRefund.setDiscountRefund(jsonObject.getJSONObject("amount").getInteger("discount_refund"));
                sOrderRefund.setCurrency(jsonObject.getJSONObject("amount").getString("currency"));
                orderRefundService.save(sOrderRefund);

            } else {
                result = "申请退款失败：failed,resp code = " + statusCode+ ",return body = " + EntityUtils.toString(response.getEntity());
                log.info(result);
                throw new IOException(result);
            }
        } finally {
            response.close();
        }

        return jsonObject;
    }

    /**
     * 官方接口地址：https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_5_11.shtml
     * @param request
     * @param response
     * @return
     * @throws Exception
     */
    @Override
    public String PayRefundNotify(HttpServletRequest request, HttpServletResponse response) throws Exception {
        JSONObject map = new JSONObject();
        String result = WxUtil.readData(request);
        // 需要通过证书序列号查找对应的证书，verifyNotify 中有验证证书的序列号
        String plainText = WxUtil.verifyNotify(result, apiV3Key);
        if (StringUtils.isNotEmpty(plainText)) {
            response.setStatus(200);
            map.put("code", "SUCCESS");
            map.put("message", "SUCCESS");
            JSONObject jsonObject=JSONObject.parseObject(plainText);
            String refundId=jsonObject.getString("refund_id");//微信退款单号
            String refundStatus=jsonObject.getString("refund_status");//退款状态，枚举值：SUCCESS：退款成功 CLOSE：退款关闭
            String successTime=jsonObject.getString("success_time");//退款成功时间
            UpdateWrapper<SOrderRefund> wrapper=new UpdateWrapper();
            wrapper.eq("refund_id",refundId);
            wrapper.set("status",refundStatus);
            wrapper.set("success_time",successTime);
            orderRefundService.update(wrapper);
            //退款成功后，业务逻辑操作
        } else {
            response.setStatus(500);
            map.put("code", "ERROR");
            map.put("message", "签名错误");
        }
        //通知应答
        //支付通知http应答码为200或204才会当作正常接收，当回调处理异常时，应答的HTTP状态码应为500，或者4xx
        response.setCharacterEncoding("utf-8");
        response.setContentType("application/json; charset=utf-8");
        BufferedOutputStream out = new BufferedOutputStream(response.getOutputStream());
        out.write(plainText.getBytes());
        out.flush();
        out.close();
        return null;
    }


    /**
     * 创建支付分订单
     * @param orderNo
     * @param total
     * @throws IOException
     */
    public JSONObject CreatePaysocreOrder(String orderNo, BigDecimal total) throws IOException, InvalidKeySpecException, NoSuchAlgorithmException, InvalidKeyException, SignatureException {
        SUser sysUser = (SUser) SecurityUtils.getSubject().getPrincipal();
        String openid=sysUser.getOpenid();

        File directory = new File("..");// 参数为空
        String courseFile = directory.getCanonicalPath()+"/apiclient_key.pem";
        PrivateKey privateKey= WxUtil.getPrivateKey(courseFile);

        JSONObject map = new JSONObject();

        // 加载平台证书（mchId：商户号,mchSerialNo：商户证书序列号,apiV3Key：V3秘钥）
        AutoUpdateCertificatesVerifier verifier = new AutoUpdateCertificatesVerifier(new WechatPay2Credentials(mchId, new PrivateKeySigner(mchSerialNo, privateKey)),apiV3Key.getBytes("utf-8"));

        // 初始化httpClient
        HttpClient httpClient = WechatPayHttpClientBuilder.create().withMerchant(mchId, mchSerialNo, privateKey).withValidator(new WechatPay2Validator(verifier)).build();

        //请求URL
        HttpPost httpPost = new HttpPost(WxConstant.paysocreCreate);

        //封装请求参数
        SelectPayOrderOutDto order=orderMapper.selectPayOrderById(orderNo);
        WXScoreOrderVo orderVo=new WXScoreOrderVo();
        orderVo.setAppid(appId);
        orderVo.setOpenid(openid);
        orderVo.setOut_order_no(orderNo);
        orderVo.setService_id(serviceId);
        orderVo.setService_introduction("信言绘本");
        orderVo.setNeed_user_confirm(true);
        //服务时间段
        TimeRange timeRange=new TimeRange();
        timeRange.setStart_time(WxUtil.DateToStr(order.getBorrowStartTime(),"yyyyMMdd"));
        timeRange.setStart_time_remark("借阅开始时间");
        timeRange.setEnd_time(WxUtil.DateToStr(order.getBorrowEndTime(),"yyyyMMdd"));
        timeRange.setEnd_time_remark("借阅结束时间");
        orderVo.setTime_range(timeRange);
        //订单风险金
        total=total.multiply(new BigDecimal(100));
        RiskFund riskFund=new RiskFund();
        riskFund.setName("DEPOSIT");
        riskFund.setAmount(total);
        orderVo.setRisk_fund(riskFund);
        orderVo.setNotify_url(scoreNotifyUrl);

        StringEntity entity = new StringEntity(JSONObject.toJSONString(orderVo),"utf-8");
        entity.setContentType("application/json");
        httpPost.setEntity(entity);
        httpPost.setHeader("Accept", "application/json");

        //完成签名并执行请求
        String packageStr= "";
        String orderId="";
        CloseableHttpResponse response = (CloseableHttpResponse) httpClient.execute(httpPost);
        int statusCode = response.getStatusLine().getStatusCode();
        if (statusCode == 200) {
            log.info("创建支付分订单success,return body = " + EntityUtils.toString(response.getEntity()));
            JSONObject jsonObject = JSONObject.parseObject(EntityUtils.toString(response.getEntity()));
            SOrderPayScore orderPayScore=JSON.toJavaObject(jsonObject,SOrderPayScore.class);
            orderPayScore.setPackageStr(jsonObject.getString("package"));
            orderPayScore.setName(jsonObject.getJSONObject("risk_fund").getString("name"));
            orderPayScore.setAmount(jsonObject.getJSONObject("risk_fund").getInteger("amount"));
            orderPayScore.setDescription(jsonObject.getJSONObject("risk_fund").getString("description"));
            orderPayScore.setStartTime(jsonObject.getJSONObject("time_range").getDate("start_time"));
            orderPayScore.setEndTime(jsonObject.getJSONObject("time_range").getDate("start_time"));
            orderPayScore.setStartTimeRemark(jsonObject.getJSONObject("time_range").getString("start_time_remark"));
            orderPayScore.setEndTimeRemark(jsonObject.getJSONObject("time_range").getString("end_time_remark"));
            orderPayScoreService.save(orderPayScore);

            packageStr = jsonObject.getString("package");
            orderId=jsonObject.getString("orderId");
            //更新微信支付服务订单号
            Map<String,Object> param=new HashMap<>();
            param.put("orderNo",orderNo);
            param.put("orderId",orderId);
            orderMapper.updateOrderIdByOrderno(param);
        }else{
            String error = "创建支付分订单failed,resp code = " + statusCode+ ",return body = " + EntityUtils.toString(response.getEntity());
            log.info(error);
            throw new IOException(error);
        }
        JSONObject exResult = new JSONObject();
        //随机字符串  根据自己工具类写
        String nonceStr = RandomStringUtils.randomAlphanumeric(5);
        //时间戳 根据自己工具类写
        String timeStamp = String.valueOf(System.currentTimeMillis());
        String pendingPaySign = mchId + "\n" +"packageStr"+"\n"+ timeStamp + "\n" + nonceStr + "\n" + "RSA" + "\n";
        String paySign = SignUtil.encodeBase64(SignUtil.sign256(pendingPaySign, privateKey));
        map.put("mch_id", mchId);//商户号
        map.put("package", packageStr);//扩展字符串	可在【创建订单】接口的返回字段package中获取。
        map.put("timestamp", timeStamp);//时间戳	生成签名时间戳，单位秒
        map.put("nonce_str", nonceStr);//随机字符串	生成签名随机串。由数字、大小写字母组成，长度不超过32位。
        map.put("sign_type", "RSA");//签名方式	签名类型，仅支持HMAC-SHA256。
        map.put("sign", paySign);//签名	使用字段mch_id、package、timestamp、nonce_str、sign_type 按照签名生成算法计算得出的签名值。
        return map;
    }


    @Override
    public String scoreNotifyResult(HttpServletRequest request, HttpServletResponse response) throws Exception {
        JSONObject map = new JSONObject();
        String result = WxUtil.readData(request);
        // 需要通过证书序列号查找对应的证书，verifyNotify 中有验证证书的序列号
        String plainText = WxUtil.verifyNotify(result, apiV3Key);
        if (StringUtils.isNotEmpty(plainText)) {
            response.setStatus(200);
            map.put("code", "SUCCESS");
            map.put("message", "SUCCESS");

            JSONObject jsonObject=JSONObject.parseObject(plainText);
            log.info("微信支付分回调通知结果："+jsonObject.toJSONString());
            String orderId = jsonObject.getString("order_id");//订单
            String state = jsonObject.getString("state");//服务订单状态	枚举值：DOING：服务订单进行中
            UpdateWrapper<SOrderPayScore> updateWrapper=new UpdateWrapper<>();
            updateWrapper.eq("order_id",orderId);
            updateWrapper.set("state",state);
            orderPayScoreService.update(updateWrapper);

            String orderNo=jsonObject.getString("out_order_no");
            String openid = jsonObject.getString("openid");//用户
            updateOrder(orderNo,state,openid);
        } else {
            response.setStatus(500);
            map.put("code", "ERROR");
            map.put("message", "签名错误");
        }
        //通知应答
        //支付通知http应答码为200或204才会当作正常接收，当回调处理异常时，应答的HTTP状态码应为500，或者4xx
        response.setCharacterEncoding("utf-8");
        response.setContentType("application/json; charset=utf-8");
        BufferedOutputStream out = new BufferedOutputStream(response.getOutputStream());
        out.write(plainText.getBytes());
        out.flush();
        out.close();


        return null;
    }

    /**
     * 取消支付分订单
     * 官方接口文档地址： https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter6_1_16.shtml
     * @param orderNo
     * @param reason
     * @return
     * @throws Exception
     */
    @Override
    public Boolean CanclePayscoreOrder(String orderNo, String reason) throws Exception {
        HttpClient httpClient=WxUtil.getHttpClient(mchId,mchSerialNo,apiV3Key);

        String url=WxConstant.cancelPaysocre.replace("{out_order_no}",orderNo);
        HttpPost httpPost=new HttpPost(url);
        CancleScoreOrderVo cancleScoreOrderVo=new CancleScoreOrderVo();
        cancleScoreOrderVo.setAppid(appId);
        cancleScoreOrderVo.setReason(reason);
        cancleScoreOrderVo.setService_id(serviceId);

        StringEntity entity = new StringEntity(JSONObject.toJSONString(cancleScoreOrderVo),"utf-8");
        httpPost.setEntity(entity);
        entity.setContentType("application/json");
        httpPost.setHeader("Accept", "application/json");
        CloseableHttpResponse response = (CloseableHttpResponse) httpClient.execute(httpPost);
        int statusCode = response.getStatusLine().getStatusCode();
        if (statusCode == 200) {
            log.info("取消支付分订单success,return body = " + EntityUtils.toString(response.getEntity()));
            JSONObject jsonObject = JSONObject.parseObject(EntityUtils.toString(response.getEntity()));
            String orderId=jsonObject.getString("order_id");
            UpdateWrapper<SOrderPayScore> updateWrapper=new UpdateWrapper<>();
            updateWrapper.eq("order_id",orderId);
            updateWrapper.set("state","CANCLED");
            orderPayScoreService.update(updateWrapper);
            return true;
        } else{
            String error = "取消支付分订单 failed,resp code = " + statusCode+ ",return body = " + EntityUtils.toString(response.getEntity());
            log.info(error);
            throw new IOException(error);
        }
    }

    /**
     * 完成支付分订单
     * 官方接口说明地址：https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter6_1_18.shtml
     * @param orderNo
     * @return
     * @throws Exception
     */
    @Override
    public Boolean CompletePayscoreOrder(String orderNo) throws Exception {
        //请求URL
        String url=WxConstant.completePaysocre.replace("{out_order_no}",orderNo);
        HttpPost httpPost = new HttpPost(url);
        HttpClient httpClient=WxUtil.getHttpClient(mchId,mchSerialNo,apiV3Key);
        //封装请求参数
        SelectPayOrderOutDto order=orderMapper.selectPayOrderById(orderNo);
        WXScoreOrderVo orderVo=new WXScoreOrderVo();
        orderVo.setAppid(appId);
        orderVo.setService_id(serviceId);
        orderVo.setTotal_amount(0);

        List<PostPayment> postPayments=new ArrayList<>();
        PostPayment postPayment=new PostPayment();
        postPayment.setAmount(0);
        postPayment.setName("租借图书服务费");
        postPayments.add(postPayment);
        orderVo.setPost_payments(postPayments);

        StringEntity entity = new StringEntity(JSONObject.toJSONString(orderVo),"utf-8");
        entity.setContentType("application/json");
        httpPost.setEntity(entity);
        httpPost.setHeader("Accept", "application/json");

        //解析结果
        CloseableHttpResponse response = (CloseableHttpResponse) httpClient.execute(httpPost);
        int statusCode = response.getStatusLine().getStatusCode();
        if (statusCode == 200) {
            log.info("完成支付分订单success,return body = " + EntityUtils.toString(response.getEntity()));
            JSONObject jsonObject = JSONObject.parseObject(EntityUtils.toString(response.getEntity()));
            String orderId=jsonObject.getString("order_id");
            UpdateWrapper<SOrderPayScore> updateWrapper=new UpdateWrapper<>();
            updateWrapper.eq("order_id",orderId);
            updateWrapper.set("state","DONE");
            orderPayScoreService.update(updateWrapper);
        }else{
            String error = "完成支付分订单failed,resp code = " + statusCode+ ",return body = " + EntityUtils.toString(response.getEntity());
            log.info(error);
            throw new IOException(error);
        }
        return null;
    }


    /**
     * 更新订单状态，支付结束后调用更新为待发货状态
     * 更新优惠券状态，支付结束后更新为已使用
     * @param orderNo
     * @param tradeState
     * @param openId
     */
    public void updateOrder(String orderNo,String tradeState,String openId){
        log.info("进入更新方法");
        Map<String,Object> map=new HashMap<>();
        map.put("orderNo",orderNo);
        if("DOING".equals(tradeState)){
            SelectPayOrderOutDto  order=orderMapper.selectPayOrderById(orderNo);
            //优惠券->已使用     图书订单->待发货    会员订单->绑定会员   订单的押金金额记录到用户总押金里
            UpdateWrapper updateWrapper=new UpdateWrapper();
            updateWrapper.eq("id",order.getCouponId());
            updateWrapper.set("coupon_status",BookConstant.COUPON_STATUS_USEED);
            couponUserService.update(updateWrapper);
            if(BookConstant.RENT_ORDER.equals(order.getOrderType())) {
                map.put("payStatus", BookConstant.TO_SEND_PAY);
                map.put("wxPayType","score");//微信分支付
            }else if(BookConstant.CARD_ORDER.equals(order.getOrderType())){
                map.put("payStatus",BookConstant.FINISHED_PAY);
                CardOrderDetailDto cardData=payOrderDetailMapper.selectCardByOrderNo(order.getOrderNo());
                memCardService.bindingMemberCard(cardData.getGoodId(),openId);
            }
            orderMapper.updatePayOrderStatus(map);
            //更新押金
            Map<String,Object> userMap=new HashMap<>();
            userMap.put("openId",openId);
            userMap.put("gold",order.getCashPledge());
            userMapper.updateUserGold(userMap);
        }
    }

}
